package com.boarsoft.boar.batch.service;

import java.util.Date;

import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Component;

import com.boarsoft.bean.ReplyInfo;
import com.boarsoft.boar.batch.biz.BatchInfoBiz;
import com.boarsoft.boar.batch.entity.BatchInfo;
import com.boarsoft.boar.common.Constants;
import com.boarsoft.common.Util;

@Component("batchInfoSvc")
public class BatchInfoServiceImpl implements BatchInfoService {
	private static final Logger log = LoggerFactory.getLogger(BatchInfoService.class);

	@Autowired
	private BatchInfoBiz infoBiz;
	@Autowired
	private BatchScheduler batchScheduler;
	@Autowired
	private ApplicationContext appCtx;

	public BatchDispatcher getDispatcher(String name) {
		if (!appCtx.containsBean(name)) {
			return null;
		}
		return (BatchDispatcher) appCtx.getBean(name);
	}

	@Override
	public BatchInfo get(String id) {
		return infoBiz.get(id);
	}

	@Override
	public ReplyInfo<Object> start(String id, String params) {
		BatchInfo o = infoBiz.get(id);
		String impl = o.getImpl();
		if (Util.strIsEmpty(impl)) {
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "impl");
		}
		BatchDispatcher bd = this.getDispatcher(impl);
		if (bd == null) {
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "impl");
		}
		int r = bd.start(id, params);
		return new ReplyInfo<Object>(true, String.valueOf(r));
	}

	@Override
	public ReplyInfo<Object> enable(String id) {
		if (Util.strIsEmpty(id)) {
			return new ReplyInfo<>(Constants.WARN_INVALID, "enable");
		}
		if (!infoBiz.enable(id)) {
			return new ReplyInfo<>(Constants.ERROR_UNKNOWN);
		}
		BatchInfo o = infoBiz.get(id);
		// 未配置CRON表达式的的批量不注册定时计划
		if (Util.strIsEmpty(o.getCron())) {
			return ReplyInfo.SUCCESS;
		}
		Date d = Util.str2date(o.getStartTime(), Util.STDDTF);
		try {
			d = batchScheduler.schedule(o, d);
			return new ReplyInfo<Object>(true, o.getId());
		} catch (ClassNotFoundException e) {
			log.error("Invalid job class {} of batch {}", o.getJob(), o, e);
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "job");
		} catch (Exception e) {
			log.error("Error on schedule {} with cron {}", o, o.getCron(), e);
			infoBiz.disable(id);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN);
		}
	}

	@Override
	public ReplyInfo<Object> disable(String id) {
		if (Util.strIsEmpty(id)) {
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "id");
		}
		if (!infoBiz.disable(id)) {
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN);
		}
		BatchInfo o = infoBiz.get(id);
		try {
			batchScheduler.unschedule(o.getId(), o.getImpl());
			return ReplyInfo.SUCCESS;
		} catch (Exception e) {
			log.error("Error on disable batch {}", id, e);
			return new ReplyInfo<Object>(Constants.ERROR_UNKNOWN);
		}
	}

	@Override
	public ReplyInfo<Object> register(BatchInfo o) {
		ReplyInfo<Object> ro = this.save(o);
		if (ro.isSuccess()) {
			return this.enable(o.getId());
		}
		return ro;
	}

	@Override
	public ReplyInfo<Object> deregister(String id) {
		if (Util.strIsEmpty(id)) {
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "id");
		}
		return this.delete(id);
	}

	protected ReplyInfo<Object> save(BatchInfo o) {
		infoBiz.save(o);
		return ReplyInfo.SUCCESS;
	}

	protected ReplyInfo<Object> delete(String id) {
		if (Util.strIsEmpty(id)) {
			return new ReplyInfo<Object>(Constants.WARN_INVALID, "delete");
		}
		ReplyInfo<Object> ri = this.disable(id);
		if (ri.isSuccess()) {
			infoBiz.delete(id);
			return ReplyInfo.SUCCESS;
		}
		return ri;
	}
}